﻿#include "tank.h"
#include <QPolygon>

std::mt19937 tank::gen(
    std::chrono::system_clock::now().time_since_epoch().count()
);
uniform_int_distribution<int> tank::dis_x(150, 1000);
uniform_int_distribution<int> tank::dis_y(150, 900);
uniform_int_distribution<int> tank::dis_angle(0, 360);


tank::tank(QWidget *parent) : QWidget(parent) {
    setFixedSize(1100, 980);
    this->r=5;
    this->x=50;
    this->y=50;
    this->angle=0;
    this->gun_angle=83;
    this->body_angle=53;
    this->isLive=1;
    this->grade=0;
    this->shoot_time=0;

}

void tank::count_xy(tank& t){
    t.body_xy.rb.x = 5 * t.r * cos((t.body_angle + t.angle) / 180.0 * pai) + t.x;
    t.body_xy.lb.x = t.x + 5 * t.r * cos(((180 - t.body_angle) + t.angle) / 180.0 * pai);
    t.body_xy.rt.x = 5 * t.r * cos((-t.body_angle + t.angle) / 180.0 * pai) + t.x;
    t.body_xy.lt.x = t.x + 5 * t.r * cos((-180 + t.body_angle + t.angle) / 180.0 * pai);

    t.body_xy.rb.y = 5 * t.r * sin((t.body_angle + t.angle) / 180.0 * pai) + t.y;
    t.body_xy.lb.y = t.y + 5 * t.r * sin(((180 - t.body_angle) + t.angle) / 180.0 * pai);
    t.body_xy.rt.y = 5 * t.r * sin((-t.body_angle + t.angle) / 180.0 * pai) + t.y;
    t.body_xy.lt.y = t.y + 5 * t.r * sin((-180 + t.body_angle + t.angle) / 180.0 * pai);

    t.gun_xy.rb.x = 8 * t.r * cos((t.gun_angle + t.angle) / 180.0 * pai) + t.x;
    t.gun_xy.lb.x = t.x + 8 * t.r * cos(((180 - t.gun_angle) + t.angle) / 180.0 * pai);
    t.gun_xy.rt.x = t.r * cos((t.angle) / 180.0 * pai) + t.x;
    t.gun_xy.lt.x = t.x + t.r * cos((180 + t.angle) / 180.0 * pai);

    t.gun_xy.rb.y = 8 * t.r * sin((t.gun_angle + t.angle) / 180.0 * pai) + t.y;
    t.gun_xy.lb.y = t.y + 8 * t.r * sin(((180 - t.gun_angle) + t.angle) / 180.0 * pai);
    t.gun_xy.rt.y = t.r * sin((t.angle) / 180.0 * pai) + t.y;
    t.gun_xy.lt.y = t.y + t.r * sin((180 + t.angle) / 180.0 * pai);
}

void tank::paintEvent(QPaintEvent *event){
    Q_UNUSED(event);
    if(this->isLive==1){
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        if(this->player==1){
            painter.setBrush(Qt::red);
        }
        else if(this->player==2){
            painter.setBrush(Qt::green);
        }
        QPolygonF body;
        body.append(QPointF(this->body_xy.lb.x,this->body_xy.lb.y));
        body.append(QPointF(this->body_xy.lt.x,this->body_xy.lt.y));
        body.append(QPointF(this->body_xy.rt.x,this->body_xy.rt.y));
        body.append(QPointF(this->body_xy.rb.x,this->body_xy.rb.y));
        QPolygonF gun;
        gun.append(QPointF(this->gun_xy.lb.x,this->gun_xy.lb.y));
        gun.append(QPointF(this->gun_xy.lt.x,this->gun_xy.lt.y));
        gun.append(QPointF(this->gun_xy.rt.x,this->gun_xy.rt.y));
        gun.append(QPointF(this->gun_xy.rb.x,this->gun_xy.rb.y));
        painter.setPen(QPen(Qt::black,1));
        painter.drawPolygon(body);
        painter.drawPolygon(gun);
        QPointF center(this->x,this->y);
        painter.drawEllipse(center,this->r,this->r);


    }
}

int tank::tank_to_wall(tank &t){
    vector<date_map>::iterator it = maps.begin();
    //lamda函数，线性回归判断是否墙壁的点在tank上
    auto list = [](int x, int y, get_rectangle_xy xy,double angle) {
        double c1, c2, c3, c4;
        double k1, k2;
        double l1, l2, l3, l4;
        k1 = tan((angle + 90) / 180 * pai);
        k2 = tan((angle + 90 + 90) / 180 * pai);
        c1 = xy.rt.y - k1 * xy.rt.x;
        c2 = xy.rt.y - k2 * xy.rt.x;
        c3 = xy.lb.y - k1 * xy.lb.x;
        c4 = xy.lb.y - k2 * xy.lb.x;
        l1 = y - k1 * x - c1;
        l2 = y - k2 * x - c2;
        l3 = y - k1 * x - c3;
        l4 = y - k2 * x - c4;
        if (l1 * l3 <= 0 && l2 * l4 <= 0) {

            return 1;
        }

        return 0;

    };
    //判断线段与线段是否相交
    auto list2 = [](int x1,int x2, int y, get_rectangle_xy xy,double angle) {
        double c1, c2, c3, c4;
        double k1, k2;
        double l1, l2, l3, l4;
        k1 = tan((angle + 90) / 180 * pai);
        k2 = tan((angle + 90 + 90) / 180 * pai);
        c1 = xy.rt.y - k1 * xy.rt.x;
        c2 = xy.rt.y - k2 * xy.rt.x;
        c3 = xy.lb.y - k1 * xy.lb.x;
        c4 = xy.lb.y - k2 * xy.lb.x;
        double temp_x1=0, temp_x2=0, temp_x3=0, temp_x4=0;
        double max_y=0, min_y = 0,temp;

        max_y = xy.rt.y;
        min_y = xy.rb.y;
        if (max_y < min_y) {
            temp = min_y;
            min_y = max_y;
            max_y = temp;
        }
        if (max_y >= y && min_y <= y) {
            temp_x1 = (y - c1) / k1;
        }


        max_y = xy.rt.y;
        min_y = xy.lt.y;
        if (max_y < min_y) {
            temp = min_y;
            min_y = max_y;
            max_y = temp;
        }
        if (max_y >= y && min_y <= y) {
            temp_x2 = (y - c1) / k2;
        }


        max_y = xy.lt.y;
        min_y = xy.lb.y;
        if (max_y < min_y) {
            temp = min_y;
            min_y = max_y;
            max_y = temp;
        }
        if (max_y >= y && min_y <= y) {
            temp_x3 = (y - c3) / k1;
        }

        max_y = xy.rb.y;
        min_y = xy.lb.y;
        if (max_y < min_y) {
            temp = min_y;
            min_y = max_y;
            max_y = temp;
        }
        if (max_y >= y && min_y <= y) {
            temp_x4 = (y - c4) / k2;
        }

        if (temp_x1 >= x1 && temp_x1 <= x2) {
            qDebug()<<temp_x1;
            return 1;
        }
        if (temp_x2 >= x1 && temp_x2 <= x2) {
            qDebug()<<temp_x2;
            return 1;
        }
        if (temp_x3 >= x1 && temp_x3 <= x2) {
            qDebug()<<temp_x3;
            return 1;
        }
        if (temp_x4 >= x1 && temp_x4 <= x2) {
            qDebug()<<temp_x4;
            return 1;
        }

        return 0;
    };

    auto list3 = [](int y1, int y2, int x, get_rectangle_xy xy, double angle) {
        double c1, c2, c3, c4;
        double k1, k2;
        double l1, l2, l3, l4;
        k1 = tan((angle + 90) / 180 * pai);
        k2 = tan((angle + 90 + 90) / 180 * pai);
        c1 = xy.rt.y - k1 * xy.rt.x;
        c2 = xy.rt.y - k2 * xy.rt.x;
        c3 = xy.lb.y - k1 * xy.lb.x;
        c4 = xy.lb.y - k2 * xy.lb.x;
        double temp_y1 = 0, temp_y2 = 0, temp_y3 = 0, temp_y4 = 0;
        double max_x = 0, min_x = 0, temp;

        max_x = xy.rt.x;
        min_x = xy.rb.x;
        if (max_x < min_x) {
            temp = min_x;
            min_x = max_x;
            max_x = temp;
        }
        if (max_x >=x  && min_x <= x) {
            temp_y1 = k1 * x + c1;
        }


        max_x = xy.rt.x;
        min_x = xy.lt.x;
        if (max_x < min_x) {
            temp = min_x;
            min_x = max_x;
            max_x = temp;
        }
        if (max_x >= x && min_x <= x) {
            temp_y2 = k2*x+c2;
        }


        max_x = xy.lt.x;
        min_x = xy.lb.x;
        if (max_x < min_x) {
            temp = min_x;
            min_x = max_x;
            max_x = temp;
        }
        if (max_x >= x && min_x <= x) {
            temp_y3 = k1 * x + c3;
        }

        max_x = xy.rb.x;
        min_x = xy.lb.x;
        if (max_x < min_x) {
            temp = min_x;
            min_x = max_x;
            max_x = temp;
        }
        if (max_x >= x && min_x <= x) {
            temp_y4 = k2 * x + c4;
        }

        if (temp_y1 >= y1 && temp_y1 <= y2) {
            //qDebug()<<5;
            return 1;
        }
        if (temp_y2 >= y1 && temp_y2 <= y2) {
            //qDebug()<<6;
            return 1;
        }
        if (temp_y3 >= y1 && temp_y3 <= y2) {
            //qDebug()<<7;
            return 1;
        }
        if (temp_y4 >= y1 && temp_y4 <= y2) {
            //qDebug()<<8;
            return 1;
        }

        return 0;
        return 0;
    };
    while (it != maps.end()) {
        //if (((int)t.angle % 90 == 0)&&(int)t.angle==t.angle) {
        if (list2(it->x1, it->x2,it->y1, t.body_xy, t.angle)) {

            return 1;
        }
        if (list2(it->x1, it->x2, it->y2, t.body_xy, t.angle)) {

            return 1;
        }
        if (list2(it->x1, it->x2, it->y1, t.gun_xy, t.angle)) {

            return 1;
        }
        if (list2(it->x1, it->x2, it->y2, t.gun_xy, t.angle)) {
            //qDebug()<<4;
            return 1;
        }

        if (list3(it->y1, it->y2, it->x1, t.body_xy, t.angle)) {
            //qDebug()<<5;
            return 1;
        }
        if (list3(it->y1, it->y2, it->x2, t.body_xy, t.angle)) {
            //qDebug()<<6;
            return 1;
        }
        if (list3(it->y1, it->y2, it->x1, t.gun_xy, t.angle)) {
            //qDebug()<<7;
            return 1;
        }
        if (list3(it->y1, it->y2, it->x2, t.gun_xy, t.angle)) {
            //qDebug()<<8;
            return 1;
        }

        if (list(it->x1, it->y1, t.body_xy, t.angle)) {
            //qDebug()<<9;
            //cout << 1;
            return 1;
        }
        if (list(it->x1, it->y2, t.body_xy, t.angle)) {
            //qDebug()<<10;
            //cout << 1;
            return 1;
        }
        if (list(it->x2, it->y1, t.body_xy, t.angle)) {
            //qDebug()<<11;
            //cout << 1;
            return 1;
        }
        if (list(it->x2, it->y2, t.body_xy, t.angle)) {
            //qDebug()<<12;
            //cout << 1;
            return 1;
        }

        if (list(it->x1, it->y1, t.gun_xy, t.angle)) {
            //qDebug()<<13;
            //cout << 1;
            return 1;
        }
        if (list(it->x1, it->y2, t.gun_xy, t.angle)) {
            //qDebug()<<14;
            //cout << 1;
            return 1;
        }
        if (list(it->x2, it->y1, t.gun_xy, t.angle)) {
            //qDebug()<<15;
            //cout << 1;
            return 1;
        }
        if (list(it->x2, it->y2, t.gun_xy, t.angle)) {
            //qDebug()<<16;
            //cout << 1;
            return 1;
        }

        it++;
    }
    return 0;
}

void tank::machine(tank &t){
    if(is_up==1){
        is_up=0;
        t.x=dis_x(gen);
        t.y=dis_y(gen);
        t.angle=dis_angle(gen);
        t.count_xy(t);
        while(t.tank_to_wall(t)){
            t.x=dis_x(gen);
            t.y=dis_y(gen);
            t.angle=dis_angle(gen);
            t.count_xy(t);
            //qDebug()<<t.x<<"  "<<t.y<<"    "<<t.angle<<"    "<<t.tank_to_wall(t);
        }
        //qDebug()<<t.x;
    }
}
